/*
 * $Id$
 *
 * Copyright ( c ) 2014 XuNuo Corporation. All Rights Reserved.
 *
 * This software is the confidential and proprietary information of XuNuo
 * Corporation ("Confidential Information").  You shall not disclose such
 * Confidential Information and shall use it only in accordance with the terms
 * of the license agreement you entered into with XuNuo Corporation or a XuNuo
 * authorized reseller (the "License Agreement"). XuNuo may make changes to the
 * Confidential Information from time to time. Such Confidential Information may
 * contain errors.
 *
 * EXCEPT AS EXPLICITLY SET FORTH IN THE LICENSE AGREEMENT, XuNuo DISCLAIMS ALL
 * WARRANTIES, COVENANTS, REPRESENTATIONS, INDEMNITIES, AND GUARANTEES WITH
 * RESPECT TO SOFTWARE AND DOCUMENTATION, WHETHER EXPRESS OR IMPLIED, WRITTEN OR
 * ORAL, STATUTORY OR OTHERWISE INCLUDING, WITHOUT LIMITATION, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY, TITLE, NON-INFRINGEMENT AND FITNESS FOR A
 * PARTICULAR PURPOSE. XuNuo DOES NOT WARRANT THAT END USER'S USE OF THE
 * SOFTWARE WILL BE UNINTERRUPTED, ERROR FREE OR SECURE.
 *
 * XuNuo SHALL NOT BE LIABLE TO END USER, OR ANY OTHER PERSON, CORPORATION OR
 * ENTITY FOR INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL
 * DAMAGES, OR DAMAGES FOR LOSS OF PROFITS, REVENUE, DATA OR USE, WHETHER IN AN
 * ACTION IN CONTRACT, TORT OR OTHERWISE, EVEN IF XuNuo HAS BEEN ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGES. XuNuo' TOTAL LIABILITY TO END USER SHALL NOT
 * EXCEED THE AMOUNTS PAID FOR THE XuNuo SOFTWARE BY END USER DURING THE PRIOR
 * TWELVE (12) MONTHS FROM THE DATE IN WHICH THE CLAIM AROSE.  BECAUSE SOME
 * STATES OR JURISDICTIONS DO NOT ALLOW LIMITATION OR EXCLUSION OF CONSEQUENTIAL
 * OR INCIDENTAL DAMAGES, THE ABOVE LIMITATION MAY NOT APPLY TO END USER.
 *
 * Copyright version 2.0
 */
package com.th.supcom.pds.phamapply.client.widget.phamdispense;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.extjs.gxt.ui.client.widget.MessageBox;
import com.google.gwt.core.client.GWT;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.th.supcom.framework.dict.web.gwt.client.model.DictModel;
import com.th.supcom.pds.common.client.model.CodeConstants;
import com.th.supcom.pds.common.enums.AvailableEnum;
import com.th.supcom.pds.common.enums.StockEnoughEnum;
import com.th.supcom.pds.common.utils.ClientUtils;
import com.th.supcom.pds.phamapply.client.model.InpPhamApplyDetailModel;
import com.th.supcom.pds.phamapply.client.model.InpPhamApplyDetailSummaryModel;
import com.th.supcom.pds.phamapply.client.service.InpPhamApplyDetailRpc;
import com.th.supcom.pds.phamapply.client.service.InpPhamApplyDetailRpcAsync;
import com.th.supcom.pds.phamapply.client.service.InpPhamDispenseDetailRpc;
import com.th.supcom.pds.phamapply.client.service.InpPhamDispenseDetailRpcAsync;

/**
 * 住院药房摆药Action
 * 
 * @author 杨冲
 */
public class PhamDispenseAction
{
    private PhamDispenseFields m_phamDispenseFields;
    private PhamDispenseNurseUnitInfoGrid m_phamDispenseNurseUnitInfoGrid;
    private PhamDispenseDetailGrid m_dispenseDetailGrid;
    private PhamDispenseCollectGrid m_collectGrid;
    private PhamDispenseOffsetGrid m_dispenseOffsetGrid;
    private PhamDispenseCurrentApplyGrid m_currentApplyGrid;
    private final String m_dispensary;
    private static InpPhamDispenseDetailRpcAsync s_dipenseDetailRpc = GWT.create (InpPhamDispenseDetailRpc.class);
    private static InpPhamApplyDetailRpcAsync s_applyDetailRpc = GWT.create (InpPhamApplyDetailRpc.class);

    /**
     * 设置药品请领文本组件
     * 
     * @param phamDispenseFields
     */
    public void setPhamDispenseFields (PhamDispenseFields phamDispenseFields)
    {

        this.m_phamDispenseFields = phamDispenseFields;
    }

    /**
     * 设置本药房需要请领的护理单元
     * 
     * @param phamDispenseNurseUnitInfoGrid
     */
    public void setPhamDispenseNurseUnitInfoGrid (PhamDispenseNurseUnitInfoGrid phamDispenseNurseUnitInfoGrid)
    {

        m_phamDispenseNurseUnitInfoGrid = phamDispenseNurseUnitInfoGrid;
    }

    /**
     * 设置药房摆药明细Grid
     * 
     * @param dispenseDetailGrid
     */
    public void setDispenseDetailGrid (PhamDispenseDetailGrid dispenseDetailGrid)
    {

        m_dispenseDetailGrid = dispenseDetailGrid;
    }

    /**
     * 设置药房摆药明细汇总Grid
     * 
     * @param collectGrid
     */
    public void setCollectGrid (PhamDispenseCollectGrid collectGrid)
    {

        m_collectGrid = collectGrid;
    }

    /**
     * 设置药房摆药明细冲抵Grid
     * 
     * @param dispenseOffsetGrid
     */
    public void setDispenseOffsetGrid (PhamDispenseOffsetGrid dispenseOffsetGrid)
    {

        m_dispenseOffsetGrid = dispenseOffsetGrid;
    }

    /**
     * 设置药房摆药明细当前摆药汇总
     * 
     * @param currentApplyGrid
     */
    public void setCurrentApplyGrid (PhamDispenseCurrentApplyGrid currentApplyGrid)
    {

        m_currentApplyGrid = currentApplyGrid;
    }

    /**
     * 构造函数
     */
    public PhamDispenseAction ()
    {
        m_dispensary = ClientUtils.getOrgModel ().getOrgCode ();
    }

    /**
     * 初始化数据
     */
    public void initData ()
    {
        getUnDispensedNurseUnit ();
        initFieldsData ();
    }

    /**
     * 获取已请领未摆药的护理单元
     */
    public void getUnDispensedNurseUnit ()
    {
        s_dipenseDetailRpc.getInpPhamApplyNurseUnit (m_dispensary,
                                                     new AsyncCallback <List <InpPhamApplyDetailModel>> ()
                                                     {

                                                         @Override
                                                         public void onSuccess (List <InpPhamApplyDetailModel> result)
                                                         {
                                                             m_phamDispenseNurseUnitInfoGrid.getStore ().removeAll ();
                                                             m_phamDispenseNurseUnitInfoGrid.getStore ().add (result);
                                                         }

                                                         @Override
                                                         public void onFailure (Throwable caught)
                                                         {
                                                             MessageBox.alert (CodeConstants.PROMPT,
                                                                               caught.getLocalizedMessage (), null);
                                                         }
                                                     });
    }

    public void getDispenseDetail ()
    {
        m_dispenseDetailGrid.getGrid ().mask ("正在查询中...");
        InpPhamApplyDetailModel model = m_phamDispenseNurseUnitInfoGrid.getGrid ().getSelectionModel ()
                                                                       .getSelectedItem ();
        if (null == model)
        {
            clear ();
            m_dispenseDetailGrid.getGrid ().unmask ();
            return;
        }
        s_dipenseDetailRpc.getApplyDetailByApplyNoAndDispensary (model.getApplyNo (), m_dispensary,
                                                                 new AsyncCallback <List <InpPhamApplyDetailModel>> ()
                                                                 {

                                                                     @Override
                                                                     public void onFailure (Throwable caught)
                                                                     {
                                                                         MessageBox.alert (CodeConstants.PROMPT,
                                                                                           caught.getLocalizedMessage (),
                                                                                           null);
                                                                         m_dispenseDetailGrid.getGrid ().unmask ();
                                                                     }

                                                                     @Override
                                                                     public void onSuccess (List <InpPhamApplyDetailModel> result)
                                                                     {
                                                                         m_dispenseDetailGrid.getStore ().removeAll ();
                                                                         m_dispenseDetailGrid.getStore ().add (result);
                                                                         getPhamApplySummary ();
                                                                         m_dispenseDetailGrid.getGrid ().unmask ();
                                                                     }
                                                                 });
    }

    /**
     * 初始化
     */
    public void initFieldsData ()
    {
        DictModel all = new DictModel ();
        all.setDictItemName ("全部");
        m_phamDispenseFields.getDispenseType ().setValue (all);
    }

    /**
     * 获取药品请领汇总
     */
    public void getPhamApplySummary ()
    {
        List <InpPhamApplyDetailModel> models = m_dispenseDetailGrid.getGrid ().getStore ().getModels ();
        List <InpPhamApplyDetailSummaryModel> summaryModels = new ArrayList <InpPhamApplyDetailSummaryModel> ();
        // 按照药品进行分组，计算每个药品的汇总
        Map <String, List <InpPhamApplyDetailModel>> phamMap = convertToMapByPhamCode (models);
        for (Map.Entry <String, List <InpPhamApplyDetailModel>> phamEntry : phamMap.entrySet ())
        {
            if (phamEntry.getValue ().isEmpty ())
            {
                continue;
            }

            InpPhamApplyDetailModel model = phamEntry.getValue ().get (0);
            // 如果药品库存不足或者不可供直接过滤掉
            if (StockEnoughEnum.NO.getEnumCode ().equals (model.getStockEnoughFlag ())
                || AvailableEnum.NO.getEnumCode ().equals (model.getApplySupplyFlag ()))
            {
                continue;
            }
            InpPhamApplyDetailSummaryModel summaryModel = statPham (phamEntry.getValue ());
            if (null == summaryModel)
            {
                continue;
            }
            summaryModels.add (statPham (phamEntry.getValue ()));
        }
        m_collectGrid.getGrid ().getStore ().removeAll ();
        m_collectGrid.getGrid ().getStore ().add (summaryModels);
        getOffsetPhamSummary ();
    }

    /**
     * 根据药品标准码将list转换成Map
     * 
     * @return
     */
    private Map <String, List <InpPhamApplyDetailModel>> convertToMapByPhamCode (List <InpPhamApplyDetailModel> models)
    {
        Map <String, List <InpPhamApplyDetailModel>> map = new HashMap <String, List <InpPhamApplyDetailModel>> ();
        for (InpPhamApplyDetailModel inpPhamApplyDetailModel : models)
        {
            List <InpPhamApplyDetailModel> temp = null;

            if (map.containsKey (inpPhamApplyDetailModel.getPhamStdCode ()))
            {
                temp = map.get (inpPhamApplyDetailModel.getPhamStdCode ());
            }
            else
            {
                temp = new ArrayList <InpPhamApplyDetailModel> ();
            }
            temp.add (inpPhamApplyDetailModel);
            map.put (inpPhamApplyDetailModel.getPhamStdCode (), temp);
        }
        return map;
    }

    /**
     * 药品统计
     */
    private InpPhamApplyDetailSummaryModel statPham (List <InpPhamApplyDetailModel> list)
    {
        InpPhamApplyDetailSummaryModel summaryModel = new InpPhamApplyDetailSummaryModel ();

        int applyCountSum = 0;
        double costSum = 0.0;
        if (list.isEmpty ())
        {
            return null;
        }

        for (InpPhamApplyDetailModel model : list)
        {
            if (null == model.getApplyAmount () || null == model.getCosts ())
            {
                continue;
            }

            applyCountSum += model.getApplyAmount ();
            costSum += model.getCosts ();
        }

        InpPhamApplyDetailModel detailModel = list.get (0);
        if (AvailableEnum.NO.getEnumCode ().equals (detailModel.getDispenseResultFlag ()))
        {
            return null;
        }

        summaryModel.setDetailSumAmount (applyCountSum);
        summaryModel.setNurseUnit (detailModel.getNurseUnit ());
        summaryModel.setPhamStdCode (detailModel.getPhamStdCode ());
        summaryModel.setDispensary (detailModel.getApplyDispensary ());
        summaryModel.setDispensaryName (detailModel.getApplyDispensaryName ());
        summaryModel.setApplySupplyFlag (detailModel.getApplySupplyFlag ());
        summaryModel.setStockEnoughFlag (detailModel.getStockEnoughFlag ());
        summaryModel.setPhamName (detailModel.getPhamName ());
        summaryModel.setPhamSpec (detailModel.getPhamSpec ());
        summaryModel.setTotalCost (costSum);
        summaryModel.setDosageUnit (detailModel.getApplyUnitName ());
        getDetailInfo (list, summaryModel);
        return summaryModel;
    }

    /**
     * 获取明细信息
     * 
     * @param list
     * @param summaryModel
     */
    private void getDetailInfo (List <InpPhamApplyDetailModel> list, InpPhamApplyDetailSummaryModel summaryModel)
    {
        // 记录每个药品,每个人的药品申请数量、实际摆药数量、冲抵数量
        Map <Long, Map <String, Integer>> countMap = new HashMap <Long, Map <String, Integer>> ();
        // 记录每个人的患者信息
        Map <Long, InpPhamApplyDetailModel> patInfoMap = new HashMap <Long, InpPhamApplyDetailModel> ();
        for (InpPhamApplyDetailModel model : list)
        {
            // 申请数量
            Integer applyCount = 0;
            // 实际摆药数量
            Integer actualCount = 0;
            // 冲抵数量
            Integer offsetCount = 0;
            // 记录单个药品的申请数量、实际摆药数量、冲抵数量
            Map <String, Integer> map = null;

            if (countMap.containsKey (model.getPaiVisitId ()))
            {
                map = countMap.get (model.getPaiVisitId ());
            }
            else
            {
                map = new HashMap <String, Integer> ();
            }

            if (map.containsKey ("applyCount"))
            {
                applyCount = map.get ("applyCount");
            }

            if (map.containsKey ("actualCount"))
            {
                actualCount = map.get ("actualCount");
            }

            if (map.containsKey ("offsetCount"))
            {
                offsetCount = map.get ("offsetCount");
            }

            applyCount += model.getApplyAmount ();

            if (null != model.getActualCount ())
            {
                actualCount += model.getActualCount ();
            }
            if (null != model.getActualOffsetAmount ())
            {
                offsetCount += model.getActualOffsetAmount ();
            }
            map.put ("applyCount", applyCount);
            map.put ("actualCount", actualCount);
            map.put ("offsetCount", offsetCount);
            countMap.put (model.getPaiVisitId (), map);
            patInfoMap.put (model.getPaiVisitId (), model);
        }
        // 摆药明细
        String dispenseInstr = "";
        // 冲抵明细
        String offsetInStr = "";
        // 实际摆药总量
        int actualDispeseCount = 0;
        for (Map.Entry <Long, Map <String, Integer>> entry : countMap.entrySet ())
        {
            dispenseInstr += patInfoMap.get (entry.getKey ()).getBedNo () + "&"
                             + countMap.get (entry.getKey ()).get ("applyCount") + ", ";
            offsetInStr += patInfoMap.get (entry.getKey ()).getBedNo () + "&"
                           + countMap.get (entry.getKey ()).get ("offsetCount") + ", ";
            actualDispeseCount += countMap.get (entry.getKey ()).get ("actualCount");
        }

        if (!dispenseInstr.isEmpty ())
        {
            dispenseInstr = dispenseInstr.substring (0, dispenseInstr.lastIndexOf (","));
        }

        if (!offsetInStr.isEmpty ())
        {
            offsetInStr = offsetInStr.substring (0, offsetInStr.lastIndexOf (","));
        }

        summaryModel.set ("dispenseInstr", dispenseInstr);
        summaryModel.set ("offsetInStr", offsetInStr);
        summaryModel.set ("actualDispeseCount", actualDispeseCount);
    }

    /**
     * 获取可冲抵的药品信息
     */
    public void getOffsetPhamSummary ()
    {
        List <InpPhamApplyDetailSummaryModel> models = m_collectGrid.getGrid ().getStore ().getModels ();
        if (models.isEmpty ())
        {
            return;
        }

        s_applyDetailRpc.getOffsetPhamSummaryList (models, new AsyncCallback <List <InpPhamApplyDetailModel>> ()
        {

            @Override
            public void onFailure (Throwable caught)
            {
                MessageBox.alert (CodeConstants.PROMPT, caught.getLocalizedMessage (), null);
            }

            @Override
            public void onSuccess (List <InpPhamApplyDetailModel> result)
            {
                addOffsetAjdustData (result, m_collectGrid.getGrid ().getStore ().getModels ());
            }
        });
    }

    /**
     * 将本次请领药品数据和可冲抵的药品信息进行对照后填入Grid中
     */
    private void addOffsetAjdustData (List <InpPhamApplyDetailModel> applyPhams,
                                      List <InpPhamApplyDetailSummaryModel> applySummarys)
    {
        ArrayList <InpPhamApplyDetailSummaryModel> models = new ArrayList <InpPhamApplyDetailSummaryModel> ();
        Map <String, InpPhamApplyDetailSummaryModel> map = convertSummaryListToMap (applySummarys);
        for (InpPhamApplyDetailModel model : applyPhams)
        {
            if (map.containsKey (model.getPhamStdCode ()))
            {
                models.add (map.get (model.getPhamStdCode ()));
            }
        }

        m_currentApplyGrid.getGrid ().getStore ().removeAll ();
        m_currentApplyGrid.getGrid ().getStore ().add (models);
        m_dispenseOffsetGrid.getGrid ().getStore ().removeAll ();
        m_dispenseOffsetGrid.getGrid ().getStore ().add (applyPhams);
    }

    /**
     * 将汇总列表转换成map
     * 
     * @param applySummarys
     * @return
     */
    private Map <String, InpPhamApplyDetailSummaryModel> convertSummaryListToMap (List <InpPhamApplyDetailSummaryModel> applySummarys)
    {
        Map <String, InpPhamApplyDetailSummaryModel> map = new HashMap <String, InpPhamApplyDetailSummaryModel> ();
        for (InpPhamApplyDetailSummaryModel model : applySummarys)
        {
            map.put (model.getPhamStdCode (), model);
        }
        return map;
    }

    /**
     * 执行摆药明细
     */
    public void execInpPhamDispense (String operator)
    {
        List <InpPhamApplyDetailModel> models = m_dispenseDetailGrid.getGrid ().getStore ().getModels ();
        final MessageBox box = MessageBox.wait ("摆药进度", "正在摆药请稍等", "摆药中...");
        s_dipenseDetailRpc.execPhamApplySheet (models, operator, m_dispensary, new AsyncCallback <Void> ()
        {

            @Override
            public void onFailure (Throwable caught)
            {
                box.close ();
                MessageBox.alert (CodeConstants.PROMPT, caught.getLocalizedMessage (), null);
            }

            @Override
            public void onSuccess (Void result)
            {
                box.close ();
                MessageBox.alert (CodeConstants.PROMPT, "摆药成功", null);
                getUnDispensedNurseUnit ();
                clear ();
            }
        });
    }

    /**
     * 清空数据
     */
    public void clear ()
    {
        m_dispenseDetailGrid.getStore ().removeAll ();
        m_collectGrid.getGrid ().getStore ().removeAll ();
        m_currentApplyGrid.getGrid ().getStore ().removeAll ();
        m_dispenseOffsetGrid.getGrid ().getStore ().removeAll ();
    }

}
